package com.github.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.DataFetcher;
import com.github.bean.ServerUser;
import com.github.bean.User;
import com.github.constant.MyConstant;
import com.github.manager.Manager;
import com.github.mq.RedisStreamService;
import com.github.pojo.HttpResult;
import com.github.pojo.WsBaseResult;
import com.github.service.AdminUserServer;
import com.github.service.UserServer;
import com.github.util.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class HttpController {
    @Autowired
    private UserServer userServer;
    @Autowired
    private AdminUserServer adminUserServer;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisStreamService redisStreamService;
    private ObjectMapper objectMapper = new ObjectMapper();

    @PostMapping("/api/account/create")
    public HttpResult addAccount(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String type = jsonNode.path("type").asText();
        String password = jsonNode.path("password").asText();
        boolean isEmpty = password.isEmpty();
        if (type.equals("single")) {
            String account = jsonNode.path("account").asText();
            User user = userServer.getUser(account);
            if (user != null) {
                return new HttpResult("账号已存在");
            }
            if (isEmpty) {
                password = Utils.getRandomString(5);
            }
            if (userServer.addUser(account, password)) {
                User user1 = new User();
                user1.setAccount(account);
                user1.setPassword(password);
                user1.setReserve(false);
                stringRedisTemplate.opsForHash().put(MyConstant.UserInfoCache, account, JSONUtil.toJsonStr(user1));
                return new HttpResult("添加成功[" + account + ":" + password + "]");
            } else {
                return new HttpResult("添加失败");
            }
        } else if (type.equals("batch")) {
            String startAccount = jsonNode.path("startAccount").asText();
            String endAccount = jsonNode.path("endAccount").asText();
            List<String> strings = new ArrayList<>();
            try {
                int start = Integer.parseInt(startAccount);
                int end = Integer.parseInt(endAccount);
                for (int i = start; i <= end; i++) {
                    String account = String.valueOf(i);
                    User user = userServer.getUser(account);
                    if (user != null) {
                        continue;
                    }
                    if (isEmpty) {
                        password = Utils.getRandomString(5);
                    }

                    if (!userServer.addUser(account, password)) {
                        return new HttpResult("[" + String.join(" ", strings) + "] 添加失败 - " + (i - 1) + "后面的账号未添加");
                    }
                    User user1 = new User();
                    user1.setAccount(account);
                    user1.setPassword(password);
                    stringRedisTemplate.opsForHash().put(MyConstant.UserInfoCache, account, JSONUtil.toJsonStr(user1));
                    strings.add(account + ":" + password);
                }
                return new HttpResult("添加成功[" + String.join(" ", strings) + "]");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return new HttpResult("未知错误");
    }

    @PostMapping("/api/account/delete")
    public HttpResult delAccount(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String type = jsonNode.path("type").asText();
        if (type.equals("single")) {
            String account = jsonNode.path("account").asText();
            if (userServer.isReserveAccount(account)) {
                return new HttpResult("保留账号不能删除");
            }
            if (userServer.delUser(account)) {
                stringRedisTemplate.opsForHash().delete(MyConstant.UserInfoCache, account);
                return new HttpResult("删除成功");
            } else {
                return new HttpResult("删除失败");
            }
        } else if (type.equals("batch")) {
            String startAccount = jsonNode.path("startAccount").asText();
            String endAccount = jsonNode.path("endAccount").asText();
            try {
                int start = Integer.parseInt(startAccount);
                int end = Integer.parseInt(endAccount);
                for (int i = start; i <= end; i++) {
                    String account = String.valueOf(i);
                    if (!userServer.delUser(account)) {
                        return new HttpResult("删除失败 - " + (i - 1) + "后面的账号未删除");
                    }
                    stringRedisTemplate.opsForHash().delete(MyConstant.UserInfoCache, account);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return new HttpResult("删除成功");
    }

    @GetMapping("/api/account/deleteall")
    public HttpResult delAllAccount() throws JsonProcessingException {
        userServer.delAllAccount();
        for (ServerUser serverUser : Manager.accountUserMap.values()) {
            if (serverUser.isServerOnline()) {
                String serveMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getServerSessionId(),"1",serveMsg);
                Utils.delayedCheck(serverUser.getServerSession(), 1000);
            }
            if (serverUser.isCardOnline()) {
                String callMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getCardSessionId(),"2", callMsg);
                Utils.delayedCheck(serverUser.getCallSession(), 1000);
            }
            if (serverUser.isVoiceOnline()) {
                String voiceMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getVoiceSessionId(),"3", voiceMsg);
                Utils.delayedCheck(serverUser.getVoiceSession(), 1000);
            }
        }
        stringRedisTemplate.delete(MyConstant.UserInfoCache);
        stringRedisTemplate.delete(MyConstant.UserLoginToken);
        stringRedisTemplate.delete(MyConstant.UserLoginAccount);
        Manager.accountUserMap.clear();
        Manager.sessionIDUserMap.clear();
//        Manager.deviceIDUserMap.clear();
        return new HttpResult("删除成功");
    }

    @GetMapping("/api/account/kickNonReserved")
    public HttpResult delAllNonReservedAccount() throws JsonProcessingException {
        List<User> users = userServer.getAllNonReservedUser();
        for (User user : users) {
            String account = user.getAccount();

            String token = (String)stringRedisTemplate.opsForHash().get(MyConstant.UserLoginAccount, account);
            if (StrUtil.isNotBlank(token)) {
                stringRedisTemplate.opsForHash().delete(MyConstant.UserLoginToken, token);
            }
            stringRedisTemplate.opsForHash().delete(MyConstant.UserLoginAccount,account);
            stringRedisTemplate.opsForHash().delete(MyConstant.UserInfoCache,account);

            ServerUser serverUser = Manager.accountUserMap.getOrDefault(account, null);
            if (serverUser == null) {
                continue;
            }
            if (serverUser.isServerOnline()) {
                String serveJson = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getServerSessionId(),"1", serveJson);
                Utils.delayedCheck(serverUser.getServerSession(), 1000);
            }
            if (serverUser.isCardOnline()) {
                String callJson = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getCardSessionId(),"2", callJson);
                Utils.delayedCheck(serverUser.getCallSession(), 1000);
            }
            if (serverUser.isVoiceOnline()) {
                String voiceMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(serverUser.getCardSessionId(),"3", voiceMsg);
                Utils.delayedCheck(serverUser.getVoiceSession(), 1000);
            }

        }
        userServer.delAllNonReservedAccount();
        return new HttpResult("删除成功");
    }

    @PostMapping("/api/account/updatePassword")
    public HttpResult updatePassword(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String type = jsonNode.path("type").asText();
        String newPassword = jsonNode.path("newPassword").asText();
        if (type.equals("single")) {
            String account = jsonNode.path("account").asText();
            User user = new User();
            user.setAccount(account);
            if (userServer.updatePassword(account, newPassword)) {
                user.setPassword(newPassword);
                stringRedisTemplate.opsForHash().put(MyConstant.UserInfoCache, account, JSONUtil.toJsonStr(user));
                return new HttpResult("密码修改成功");
            } else {
                return new HttpResult("密码修改失败");
            }
        } else if (type.equals("batch")) {
            String startAccount = jsonNode.path("startAccount").asText();
            String endAccount = jsonNode.path("endAccount").asText();
            try {
                int start = Integer.parseInt(startAccount);
                int end = Integer.parseInt(endAccount);
                for (int i = start; i <= end; i++) {
                    String account = String.valueOf(i);
                    User user = new User();
                    user.setAccount(account);
                    user.setPassword(newPassword);
                    if (!userServer.updatePassword(account, newPassword)) {
                        return new HttpResult("密码修改失败 - " + (i - 1) + "后面的账号未修改");
                    }
                    stringRedisTemplate.opsForHash().put(MyConstant.UserInfoCache, account, JSONUtil.toJsonStr(user));
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return new HttpResult("修改成功");
    }

    @PostMapping("/api/account/kick")
    public HttpResult kickAccount(@RequestBody String data) throws JsonProcessingException {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String account = jsonNode.path("account").asText();
        String device = jsonNode.path("device").asText();
        switch (device) {
            case "拉手端":
                DataFetcher.delTokenByAccount(account);
//                dataFetcher.delAccountByToken(serverUser.getToken());
                break;
        }
        ServerUser serverUser = Manager.accountUserMap.getOrDefault(account, null);
        if (serverUser == null) {
            return new HttpResult("用户不在线");
        }
        switch (device) {
            case "拉手端":
                if (serverUser.isServerOnline()) {
                    String serveJson = objectMapper.writeValueAsString(WsBaseResult.kick());
                    redisStreamService.sendMessage(serverUser.getServerSessionId(),"1", serveJson);
                    Utils.delayedCheck(serverUser.getServerSession(), 1000);
                } else {
                    return new HttpResult("用户不在线");
                }
                break;
            case "插卡端":
                if (serverUser.isCardOnline()) {
                    String callMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                    redisStreamService.sendMessage(serverUser.getCardSessionId(),"2", callMsg);
                    Utils.delayedCheck(serverUser.getCallSession(), 1000);
                } else {
                    return new HttpResult("用户不在线");
                }
                break;
            case "语音端":
                if (serverUser.isVoiceOnline()) {
                    String voiceMsg = objectMapper.writeValueAsString(WsBaseResult.kick());
                    redisStreamService.sendMessage(serverUser.getCardSessionId(),"3", voiceMsg);
                    Utils.delayedCheck(serverUser.getVoiceSession(), 1000);
                } else {
                    return new HttpResult("用户不在线");
                }
                break;
        }
        return new HttpResult("踢出成功");
    }

    @PostMapping("/api/account/status")
    public HttpResult getAccountStatus(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String account = jsonNode.get("account").asText();
        try {
            ServerUser serverUser = Manager.accountUserMap.getOrDefault(account, null);
            List<HttpResult.User> users = new ArrayList<>();
            users.add(new HttpResult.User(account, "离线", "离线", "离线"));
            String jsonString = new ObjectMapper().writeValueAsString(users);
            if (serverUser == null) {
                return new HttpResult(jsonString);
            }
            users.clear();
            HttpResult.User user = new HttpResult.User(
                    account,
                    serverUser.isServerOnline() ? "在线" : "离线",
                    serverUser.isCardOnline() ? "在线" : "离线",
                    serverUser.isVoiceOnline() ? "在线" : "离线"
            );
            users.add(user);
            jsonString = objectMapper.writeValueAsString(users);
            return new HttpResult(jsonString);
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpResult("获取失败");
        }
    }

    @PostMapping("/api/account/reserve")
    public HttpResult reserveAccount(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String account = jsonNode.get("account").asText();
        account = account.replaceAll("，", ",");
        if (!account.contains(",")) {
            if (userServer.reserveAccount(account)) {
                return new HttpResult("保留成功");
            } else {
                return new HttpResult("保留失败,请检查用户名是否正确");
            }
        } else {
            try {
                List<String> accountList = convertToAccountList(account);
                List<String> errorAccount = new ArrayList<>();
                int successAccount = 0;
                for (String accoun : accountList) {
                    if (userServer.reserveAccount(accoun)) {
                        successAccount++;
                    } else {
                        errorAccount.add(accoun);
                    }
                }
                if(errorAccount.size() == 0) {
                    return new HttpResult("共保留" + accountList.size() + "个;保留成功" + successAccount + "个");
                } else {
                    return new HttpResult("共保留" + accountList.size() + "个;保留成功" + successAccount + "个;失败" + errorAccount.size() + "个;失败账号：" + errorAccount + ";请检查失败账号是否存在");
                }
            } catch (Exception e) {
                return new HttpResult("错误: " + e.getMessage());
            }
        }
    }

    private List<String> convertToAccountList(String accountStr) {
        if (accountStr == null || accountStr.trim().isEmpty()) {
            return new ArrayList<>(); // 返回空列表而非 null
        }

        try {
            // 去除首尾空格，处理连续逗号的情况
            String[] accounts = accountStr.trim().split("\\s*,\\s*");

            // 使用 Java Stream 过滤空字符串
            List<String> accountList = Arrays.stream(accounts)
                    .filter(account -> !account.isEmpty())
                    .collect(Collectors.toList());

            if (accountList.isEmpty()) {
                throw new IllegalArgumentException("输入字符串不包含有效账户");
            }

            return accountList;

        } catch (Exception e) {
            // 处理意外异常（如 split 方法抛出的异常）
            throw new IllegalArgumentException("解析账户字符串时出错: " + e.getMessage(), e);
        }
    }

    @PostMapping("/api/account/unreserve")
    public HttpResult unReserveAccount(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        String account = jsonNode.get("account").asText();
        if (userServer.unReserveAccount(account)) {
            return new HttpResult("删除成功");
        } else {
            return new HttpResult("删除失败");
        }
    }

    @GetMapping("/api/account/reserved")
    public HttpResult getReserveAccount() {
        try {
            return new HttpResult(objectMapper.writeValueAsString(userServer.getReserveUser()));
        } catch (Exception e) {
            e.printStackTrace();
            return new HttpResult("获取失败");
        }
    }

    @PostMapping("/api/account/setdelay")
    public HttpResult setDelay(@RequestBody String data) {
        JsonNode jsonNode = Utils.toJsonNode(data);
        Manager.delay = jsonNode.get("second").asInt();
        return new HttpResult("设置成功");
    }

    @GetMapping("/api/account/getdelay")
    public HttpResult getDelay() {
        return new HttpResult(String.valueOf(Manager.delay));
    }
}
